home *** CD-ROM | disk | FTP | other *** search
- /* viewformat.c
- *
- * This contains the support routines used to handle the define
- * and view parsing routines
- */
-
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include "lex.h"
- #include "viewformat.h"
-
- /************************************************************************/
- /* */
- /* Internal structures */
- /* */
- /************************************************************************/
-
- static struct ViewFormatRecord *GViews;
- static FILE *GFile;
- extern int GFileFormat;
-
- /************************************************************************/
- /* */
- /* Change Resolution */
- /* */
- /************************************************************************/
-
- /* ChangeRes
- *
- * Change resolution
- */
-
- static long ChangeRes(long x)
- {
- if (GFileFormat == 0) return x;
- else {
- if ((x == -1) || (x == 0)) return x;
- return (4*x)/3;
- }
- }
-
- /************************************************************************/
- /* */
- /* Swap Word/Long Word */
- /* */
- /************************************************************************/
-
- /* SwapWord
- *
- * Swap the order in a word
- */
-
- static short SwapWord(short x)
- {
- unsigned char *t;
- unsigned char tmp;
-
- if (GFileFormat) {
- t = (unsigned char *)&x;
- tmp = t[0];
- t[0] = t[1];
- t[1] = tmp;
- }
-
- return x;
- }
-
- /* SwapLong
- *
- * Swap the order in a long word
- */
-
- static long SwapLong(long x)
- {
- unsigned char *t;
- unsigned char tmp;
-
- if (GFileFormat) {
- t = (unsigned char *)&x;
- tmp = t[0];
- t[0] = t[3];
- t[3] = tmp;
- tmp = t[1];
- t[1] = t[2];
- t[2] = tmp;
- }
-
- return x;
- }
-
- /************************************************************************/
- /* */
- /* Parser routines */
- /* */
- /************************************************************************/
-
- /* FindViewDefine
- *
- * Find the definition of this view
- */
-
- static ViewFormatRecord *FindViewFormat(long type)
- {
- ViewFormatRecord *vf;
-
- for (vf = GViews; vf != NULL; vf = vf->next) {
- if (vf->vtoken == type) return vf;
- }
- return NULL;
- }
-
-
- /* ParseElement
- *
- * This parses a single element in the 'define' definition
- */
-
- static ViewElemRecord *ParseElement(void)
- {
- int i;
- ViewElemRecord *ve;
-
- ve = (ViewElemRecord *)malloc(sizeof(ViewElemRecord));
- if (ve == NULL) {
- PrintError("out of memory");
- exit(1);
- }
-
- i = GetNextToken();
- if (i == KTokenBool) {
- ve->type = KViewBoolean;
- } else if (i == KTokenInteger) {
- ve->type = KViewInteger;
- } else if (i == KTokenDimension) {
- ve->type = KViewDimension;
- } else if (i == KTokenString) {
- ve->type = KViewString;
- } else {
- PrintError("Unknown element type: '%s'",GToken);
- return NULL;
- }
-
- i = GetNextToken();
- if (i != ';') {
- PrintError("Expected ';', got '%s'",GToken);
- return NULL;
- }
-
- return ve;
- }
-
- /* FlushEOR
- *
- * Flush to the end of the record. This reads ahead until I hit
- * a 'create', 'define' or 'read' symbol
- */
-
- static void FlushEOR(void)
- {
- int i;
-
- for (;;) {
- i = GetNextToken();
- if ((i == -1) || (i == KTokenCreate) || (i == KTokenDefine) || (i == KTokenRead)) break;
- }
- if (i != -1) PushBackToken(i);
- }
-
- /* ParseDefine
- *
- * Parse a definition
- */
-
- static void ParseDefine(void)
- {
- long l;
- int i;
- ViewFormatRecord *vf;
- ViewElemRecord *ve;
- ViewElemRecord *end;
-
- /*
- * Read in the header
- */
-
- i = GetNextToken();
- if (i != KLexString) {
- PrintError("Expected type string, got '%s'",GToken);
- FlushEOR();
- return;
- }
-
- l = *((long *)GToken);
- if (FindViewFormat(l)) {
- PrintError("View type \"%s\" already defined",GToken);
- FlushEOR();
- return;
- }
-
- if ('{' != (i = GetNextToken())) {
- PrintError("Expected '{', got '%s'",GToken);
- FlushEOR();
- return;
- }
-
- vf = (ViewFormatRecord *)malloc(sizeof(ViewFormatRecord));
- if (vf == NULL) {
- PrintError("out of memory");
- exit(1);
- }
-
- /*
- * Parse the contents
- */
-
- vf->vtoken = l;
- vf->list = NULL;
- vf->base = NULL;
-
- i = GetNextToken();
- if (i == KTokenClass) {
- /*
- * Class definition provided
- */
-
- i = GetNextToken();
- if (i != KLexString) {
- PrintError("Expected type string, got '%s'",GToken);
- FlushEOR();
- return;
- }
-
- l = *((long *)GToken);
- if (NULL == (vf->base = FindViewFormat(l))) {
- PrintError("View type \"%s\" not defined",GToken);
- FlushEOR();
- return;
- }
-
- i = GetNextToken();
- if (i != ';') {
- PrintError("Expected ';', got '%s'",GToken);
- FlushEOR();
- return;
- }
- } else {
- PushBackToken(i);
- }
-
- /*
- * Read in the definition itself
- */
-
- end = NULL;
- for (;;) {
- i = GetNextToken();
- if (i == '}') break;
- PushBackToken(i);
- ve = ParseElement();
-
- if (ve == NULL) {
- FlushEOR();
- return;
- }
-
- if (end) {
- end->next = ve;
- } else {
- vf->list = ve;
- }
- end = ve;
- ve->next = NULL;
- }
-
- /*
- * Find terminating ';'
- */
-
- i = GetNextToken();
- if (i != ';') {
- PrintError("Expected ';', got '%s'",GToken);
- PushBackToken(i);
- }
-
- vf->next = GViews;
- GViews = vf;
- }
-
- /************************************************************************/
- /* */
- /* Parse View Records */
- /* */
- /************************************************************************/
-
- /* ParseArgument
- *
- * Parse a simple argument
- */
-
- static int ParseArgument(ViewElemRecord *ve)
- {
- int i;
- long l;
- unsigned char c;
- short b;
-
- if (ve->type == KViewBoolean) {
- i = GetNextToken();
- if (i == KTokenTrue) {
- b = 1;
- } else if (i == KTokenFalse) {
- b = 0;
- } else {
- PrintError("Expected 'true' or 'false' argument; got '%s'",GToken);
- return -1;
- }
- b = SwapWord(b);
- fwrite(&b,sizeof(b),1,GFile);
- } else if (ve->type == KViewInteger) {
- i = GetNextToken();
- if (i == KLexInteger) {
- l = SwapLong(GInteger);
- fwrite(&l,sizeof(l),1,GFile);
- } else {
- PrintError("Expected integer, got '%s'",GToken);
- return -1;
- }
- } else if (ve->type == KViewDimension) {
- i = GetNextToken();
- if (i == KLexInteger) {
- l = SwapLong(ChangeRes(GInteger));
- fwrite(&l,sizeof(l),1,GFile);
- } else {
- PrintError("Expected integer, got '%s'",GToken);
- return -1;
- }
- } else if (ve->type == KViewString) {
- i = GetNextToken();
- if (i == KLexString) {
- c = strlen(GToken);
- fwrite(&c,1,1,GFile);
- if (c) fwrite(GToken,c,1,GFile);
- if ((c % 2) == 0) {
- c = 0;
- fwrite(&c,1,1,GFile); /* Word align */
- }
- } else {
- PrintError("Expected string, got '%s'",GToken);
- return -1;
- }
- } else {
- PrintError("Internal error");
- return -1;
- }
- return 0;
- }
-
- /* ParseViewArgument
- *
- * This parses the specified view record, writing it out to the
- * file. This barfs when it doesn't match; when I hit the end, I don't care
- */
-
- static int ParseViewArgument(ViewFormatRecord *vf)
- {
- int i;
- ViewElemRecord *ve;
-
- if (vf->base) {
- if (ParseViewArgument(vf->base)) return -1;
- }
- for (ve = vf->list; ve != NULL; ve = ve->next) {
- if (ParseArgument(ve)) return -1;
- i = GetNextToken(); /* Grab optional ',' */
- if (i != ',') PushBackToken(i);
- }
- return 0;
- }
-
- /* ParseViewRecord
- *
- * Given a 'view' keyword, this parses the contents
- */
-
- static long ParseViewRecord()
- {
- ViewFormatRecord *vf;
- int i;
- long t;
- long hoff;
- ViewRecord vr;
- ViewRecord nvr;
- long noff;
- long end;
-
- /*
- * Get the type
- */
-
- i = GetNextToken();
- if (i != KLexString) {
- PrintError("Expected string, got '%s'",GToken);
- return -1;
- }
- t = *((long *)GToken);
- if (NULL == (vf = FindViewFormat(t))) {
- PrintError("View \"%s\" not defined",GToken);
- return -1;
- }
-
- i = GetNextToken();
- if (i != '{') {
- PrintError("Expected '{', got '%s'",GToken);
- return -1;
- }
-
- /*
- * Now that we have the type, initialize and write out the
- * view header
- */
-
- hoff = ftell(GFile);
- vr.viewsize = SwapLong(0);
- vr.viewchild = SwapLong(0);
- vr.viewsibling = SwapLong(0);
- vr.viewtype = SwapLong(t);
- fwrite(&vr,sizeof(vr),1,GFile);
- vr.viewsize = SwapLong(vr.viewsize);
- vr.viewchild = SwapLong(vr.viewchild);
- vr.viewsibling = SwapLong(vr.viewsibling);
-
- /*
- * Parse the arguments
- */
-
- if (ParseViewArgument(vf)) return -1;
- vr.viewsize = ftell(GFile) - hoff;
-
- /*
- * Now parse the subviews (if any)
- */
-
- end = -1;
- for (;;) {
- i = GetNextToken();
- if (i == '}') break; /* No more subviews */
- if (i == ',') continue; /* Skip random ',' */
-
- if (i != KTokenView) {
- PrintError("Expected view definition, got '%s'",GToken);
- return -1;
- }
-
- noff = ParseViewRecord();
- if (noff == -1) return -1;
-
- /*
- * Attach to eol
- */
-
- if (end == -1) {
- vr.viewchild = noff - hoff;
- } else {
- /*
- * Attach to last child through sibling chain
- */
-
- fseek(GFile,end,SEEK_SET);
- fread(&nvr,sizeof(nvr),1,GFile);
- nvr.viewsibling = SwapLong(noff - end); /* To sibling */
- fseek(GFile,end,SEEK_SET);
- fwrite(&nvr,sizeof(nvr),1,GFile);
- fseek(GFile,0L,SEEK_END);
- }
- end = noff;
- }
-
- /*
- * Now that we've done the subview, update my own record
- */
-
- fseek(GFile,hoff,SEEK_SET);
- vr.viewsize = SwapLong(vr.viewsize);
- vr.viewchild = SwapLong(vr.viewchild);
- vr.viewsibling = SwapLong(vr.viewsibling);
- fwrite(&vr,sizeof(vr),1,GFile);
- fseek(GFile,0L,SEEK_END);
-
- /*
- * And return the file location where I am
- */
-
- return hoff;
- }
-
- /* ParseCreate
- *
- * Parse the create statement
- */
-
- static void ParseCreate(void)
- {
- int i;
- long l;
-
- i = GetNextToken();
- if (i != KLexString) {
- PrintError("Expected file name, got '%s'",GToken);
- FlushEOR();
- return;
- }
-
- if (GFileFormat == 0) strcat(GToken,"_mac.vres");
- else strcat(GToken,"_win.vres");
-
- GFile = fopen(GToken,"wb+");
- if (GFile == NULL) {
- PrintError("Unable to open '%s' for writing",GToken);
- FlushEOR();
- return;
- }
- printf(" Writing \"%s\"\n",GToken);
-
- i = GetNextToken();
- if (i != KTokenView) {
- PrintError("Expected 'view', got '%s'",GToken);
- FlushEOR();
- fclose(GFile);
- return;
- }
-
- ParseViewRecord();
-
- fclose(GFile);
-
- i = GetNextToken();
- if (i != ';') {
- PrintError("Expected ';', got '%s'",GToken);
- PushBackToken(i);
- }
- }
-
-
- /* ParseRead
- *
- * Parse the read command
- */
-
- static void ParseRead(void)
- {
- int i;
- char buffer[256];
-
- i = GetNextToken();
- if (i != KLexString) {
- PrintError("Expected file name, got '%s'",GToken);
- FlushEOR();
- return;
- }
-
- strcpy(buffer,GToken);
- i = GetNextToken();
- if (i != ';') {
- PrintError("Expected ';', got '%s'",GToken);
- FlushEOR();
- }
-
- ReadLexFile(buffer);
- }
-
- /************************************************************************/
- /* */
- /* Main Parser Loop */
- /* */
- /************************************************************************/
-
- /* ParseFile
- *
- * Parse this file
- */
-
- void ParseFile(char *f)
- {
- int i;
- ViewFormatRecord *vf;
- ViewElemRecord *ve;
-
- /* Clear the current pointer */
- GViews = NULL;
-
- /* initialize lex engine */
- InitLexEngine();
- ReadLexFile(f);
-
- /* Parse the file */
- for (;;) {
- i = GetNextToken();
- if (i == KTokenDefine) ParseDefine();
- else if (i == KTokenCreate) ParseCreate();
- else if (i == KTokenRead) ParseRead();
- else if (i == -1) break;
- else {
- PrintError("Unexpected token '%s'",GToken);
- FlushEOR();
- }
- }
-
- /* Done */
- EndLexEngine();
-
- /* Release memory */
- while (GViews) {
- vf = GViews;
- GViews = GViews->next;
-
- while (vf->list) {
- ve = vf->list;
- vf->list = ve->next;
-
- free((void *)ve);
- }
-
- free((void *)vf);
- }
- }
-